
package com.manbu.live.user.provider.service.impl;

import com.alibaba.fastjson.JSON;
import com.manbu.live.common.interfaces.utils.ConvertBeanUtils;
import com.manbu.live.farmework.redis.starter.keys.UserProviderCacheKeyBuilder;
import com.manbu.live.user.constants.CatchAsyncDeleteCode;
import com.manbu.live.user.constants.UserProviderRocketMqTopicNames;
import com.manbu.live.user.constants.UserTagEnum;
import com.manbu.live.user.constants.UserTagFieldNameConstants;
import com.manbu.live.user.dto.UserCatchAsyncDeleteDTO;
import com.manbu.live.user.dto.UserTagDTO;
import com.manbu.live.user.provider.dao.mapper.IUserTagMapper;
import com.manbu.live.user.provider.dao.po.UserTagPO;
import com.manbu.live.user.provider.service.IUserTagService;
import com.manbu.live.user.utils.TagInfoUtils;
import jakarta.annotation.Resource;
import org.apache.rocketmq.client.producer.MQProducer;
import org.apache.rocketmq.common.message.Message;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.data.redis.core.RedisTemplate;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author hanWang
 * @Title:
 * @Package
 * @Description:
 * @date 2024/1/2411:50 PM
 */
@Service
public class UserTagServiceImpl implements IUserTagService {
    @Resource
    private IUserTagMapper userTagMapper;
    @Resource
    private RedisTemplate<String, UserTagDTO> redisTemplate;
    @Resource
    private UserProviderCacheKeyBuilder userProviderCacheKeyBuilder;
    /**
     * 采用rocketmq 延迟双删
     */
    @Resource
    private MQProducer producer;
    @Override
    public boolean setTag(Long userId, UserTagEnum userTagEnum) {

//        if (containTag(userId,userTagEnum.IS_OLD_USER)){
//            // todo 如果存在某阿斯顿撒奥奥些标签 就执行一些操作
//        }else {
//            // todo 不存在就 打上标签再执行某些操作
//            userTagMapper.setTag(userId,userTagEnum.getFiledName(),userTagEnum.getTag())
//        }
//        if (this.setTag(userId,UserTagEnum.IS_OLD_USER)){
//            // todo
//        }else {
//           //todo
//        }
//
//          尝试 update true return
//          设置了标签，没有记录（两种失败场景）
//          select is null ， insert return update
        boolean updateStatus = userTagMapper.setTag(userId, userTagEnum.getFiledName(), userTagEnum.getTag()) > 0;
        if (updateStatus){
            deleteUserDTOFromRedisById(userId);
            return true;
        }
        UserTagPO userTagPO = userTagMapper.selectById(userId);
        if (userTagPO!=null){
            return false;
        }
        String setNxKey = userProviderCacheKeyBuilder.buildTagLockKey(userId);
        String setNxResult = redisTemplate.execute(new RedisCallback<Object>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                // 取出redis的key 序列化器
                RedisSerializer keySerializer = redisTemplate.getKeySerializer();
                RedisSerializer valueSerializer = redisTemplate.getValueSerializer();
                String result = (String) connection.execute("set",
                        keySerializer.serialize(setNxKey),
                        valueSerializer.serialize("-1"),
                        "NX".getBytes(StandardCharsets.UTF_8),
                        "EX".getBytes(StandardCharsets.UTF_8),
                        "3".getBytes(StandardCharsets.UTF_8));


                return result;
            }
        }).toString();
        if (!"OK".equals(setNxResult)){
            return false;
        }
        userTagPO = new UserTagPO();
        userTagPO.setUserId(userId);
        userTagMapper.insert(userTagPO);
        boolean flag = userTagMapper.setTag(userId, userTagEnum.getFiledName(), userTagEnum.getTag()) > 0;
        redisTemplate.delete(setNxKey);
        return flag;
    }

    @Override
    public boolean cancelTag(Long userId, UserTagEnum userTagEnum) {
        boolean flag = userTagMapper.cancelTag(userId, userTagEnum.getFiledName(), userTagEnum.getTag()) > 0;
        if (!flag){
            return false;
        }
        deleteUserDTOFromRedisById(userId);
        return true;
    }

    @Override
    public boolean containTag(Long userId, UserTagEnum userTagEnum) {

        UserTagDTO userTagDTO = this.queryByUserIdFromRedis(userId);
        if (userTagDTO == null){
            return false;
        }
        String filedName = userTagEnum.getFiledName();
        if (UserTagFieldNameConstants.TAG_INFO_01.equals(filedName)){
            return TagInfoUtils.isContain(userTagDTO.getTagInfo01(),userTagEnum.getTag());
        }else if (UserTagFieldNameConstants.TAG_INFO_02.equals(filedName)){
            return TagInfoUtils.isContain(userTagDTO.getTagInfo01(),userTagEnum.getTag());
        }else if (UserTagFieldNameConstants.TAG_INFO_03.equals(filedName)){
            return TagInfoUtils.isContain(userTagDTO.getTagInfo01(),userTagEnum.getTag());
        }else if (UserTagFieldNameConstants.TAG_INFO_04.equals(filedName)){
            return TagInfoUtils.isContain(userTagDTO.getTagInfo01(),userTagEnum.getTag());
        }else{
            return TagInfoUtils.isContain(userTagDTO.getTagInfo01(),userTagEnum.getTag());
        }
    }

    /**
     * 从redis中查询用户标签信息
     * @param userId
     */
    private UserTagDTO queryByUserIdFromRedis(Long userId){
        String userTagInfoKey = userProviderCacheKeyBuilder.buildUserTagInfoKey(userId);
        UserTagDTO userTagDTO = redisTemplate.opsForValue().get(userTagInfoKey);
        if (userTagDTO != null){
            return userTagDTO;
        }
        UserTagPO userTagPO = userTagMapper.selectByUserId(userId);
        if (userTagPO == null){
            return null;
        }
        userTagDTO = ConvertBeanUtils.convert(userTagPO, UserTagDTO.class);
        redisTemplate.opsForValue().set(userTagInfoKey,userTagDTO);
        return userTagDTO;


    }

    /**
     * 删除redis中的用户标签
     * @param userId
     */
    private void deleteUserDTOFromRedisById(Long userId){
        try {
            UserCatchAsyncDeleteDTO userCatchAsyncDeleteDTO = new UserCatchAsyncDeleteDTO();
            userCatchAsyncDeleteDTO.setCode(CatchAsyncDeleteCode.USER_TAG_INFO_DELETE.getCode());
            Map<String,Object> jsonParam = new HashMap<>();
            jsonParam.put("userId",userId);
            userCatchAsyncDeleteDTO.setJson(JSON.toJSONString(jsonParam));
            String userTagInfoKey = userProviderCacheKeyBuilder.buildUserTagInfoKey(userId);
            redisTemplate.delete(userTagInfoKey);
            Message message = new Message();
            message.setTopic(UserProviderRocketMqTopicNames.USER_CATCH_ASYNC_DELETE_TOPIC);
            message.setDelayTimeLevel(1);
            message.setBody(JSON.toJSONString(userCatchAsyncDeleteDTO).getBytes());
            producer.send(message);
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}
